use crate::db::{
    dao::{BaseDao, UpdateDao},
    po::{
        self,
        endpoint_peer_wireguard_config::{ActiveModel, Column, Entity, Model},
    },
};
use sea_orm::{ColumnTrait, DatabaseConnection};
use sea_query::IntoCondition;

#[derive(Debug, Default, Clone, Eq, PartialEq)]
pub struct Filter {
    pub endpoint_peer_id: Option<String>,
}

impl IntoCondition for Filter {
    fn into_condition(self) -> sea_query::Condition {
        let mut condition = sea_query::Condition::all();
        if let Some(endpoint_peer_id) = self.endpoint_peer_id {
            condition = condition.add(Column::EndpointPeerId.eq(endpoint_peer_id));
        }

        condition
    }
}

#[derive(Debug, Default, Clone, PartialEq)]
pub struct UpdateParams {
    pub wireguard_peer_endpoint: po::ActiveValue<Option<String>>,
    pub wireguard_peer_persistent_keepalive: po::ActiveValue<Option<u32>>,
}

impl Into<ActiveModel> for UpdateParams {
    fn into(self) -> ActiveModel {
        ActiveModel {
            id: Default::default(),
            endpoint_peer_id: Default::default(),
            wireguard_peer_endpoint: self.wireguard_peer_endpoint,
            wireguard_peer_persistent_keepalive: self.wireguard_peer_persistent_keepalive,
            create_timestamp_millis: Default::default(),
            update_timestamp_millis: Default::default(),
        }
    }
}

#[async_trait::async_trait]
pub trait EndpointPeerWireguardConfigDao:
    BaseDao<
        Model = Model,
        ActiveModel = ActiveModel,
        Entity = Entity,
        Column = Column,
        Filter = Filter,
    > + UpdateDao<UpdateParams = UpdateParams>
{
}

#[derive(Clone)]
pub struct DefaultEndpointPeerWireguardConfigDao {
    db: DatabaseConnection,
}

impl DefaultEndpointPeerWireguardConfigDao {
    pub fn new(db: DatabaseConnection) -> Self {
        Self { db }
    }
}

#[async_trait::async_trait]
impl EndpointPeerWireguardConfigDao for DefaultEndpointPeerWireguardConfigDao {
}

#[async_trait::async_trait]
impl BaseDao for DefaultEndpointPeerWireguardConfigDao {
    type Model = Model;
    type ActiveModel = ActiveModel;
    type Entity = Entity;
    type Column = Column;
    type Filter = Filter;

    fn db(&self) -> &DatabaseConnection {
        &self.db
    }
}

#[async_trait::async_trait]
impl UpdateDao for DefaultEndpointPeerWireguardConfigDao {
    type UpdateParams = UpdateParams;
}
